package br.uvv.sao.managedBean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.primefaces.event.UnselectEvent;
import org.primefaces.model.LazyDataModel;

import br.uvv.sao.domain.AlternativaBase;
import br.uvv.sao.domain.PalavraChave;
import br.uvv.sao.domain.Professor;
import br.uvv.sao.domain.QuestaoBase;
import br.uvv.sao.domain.Usuario;
import br.uvv.sao.enums.TipoGrauDificuldade;
import br.uvv.sao.rn.QuestaoRN;
import br.uvv.sao.util.DAOException;
import br.uvv.sao.util.InitUtil;
import br.uvv.sao.util.MsgUtil;
import br.uvv.sao.util.Util;

@SuppressWarnings("serial")
public class QuestaoBean implements Serializable {
	private static final long serialVersionUID = 1L;
	
	private QuestaoRN questaoRN;
	
	/*
	 * Listas
	 */
	private LazyDataModel<QuestaoBase> questaoBaseList;
	private List<AlternativaBase> alternativaBaseList;
	private List<AlternativaBase> alternativaRemoverList;
	private LazyDataModel<PalavraChave> palavraChaveList;
	
	/*
	 * Instancias
	 */
	private QuestaoBase questaoBaseInstance;
	private AlternativaBase alternativaBaseInstance;
	private AlternativaBase alternativaCorretaInstance;
	private PalavraChave palavraChaveInstance;
	private Professor professorInstance;
	
	/*
	 * Temporárias
	 */
	private QuestaoBase questaoBaseTemp;
	private AlternativaBase alternativaBaseTemp;
	private AlternativaBase alternativaCorretaTemp;
	private PalavraChave palavraChaveTemp;
	private String variavelBusca;
	private String variavelBuscaAssunto;
	private String varBuscaAssunto;
	private TipoGrauDificuldade varBuscaDificuldade;
	private String varBuscaCabecalho;
	private Boolean questaoEmEdicao;
	
	/*
	 * Métodos
	 */
	
	public String questao(){
		init();
		return "/views/questoes/show.xhtml";
	}
	
	public void create(){
		init();
		questaoEmEdicao = true;
		questaoBaseInstance.setProfessor(professorInstance);
	}
	
	public void desistirCreate(){
		if(questaoBaseInstanceNaoEhNula()){
			try {
				questaoBaseInstance = questaoRN.getQuestao(questaoBaseInstance.getId());
				alternativaBaseList = questaoBaseInstance.getAlternativas();
				alternativaCorretaInstance = questaoBaseInstance.getAlternativaCorreta();
				edit();
				questaoEmEdicao = false;
			} catch (DAOException e) {
				e.printStackTrace();
			}
		}else{
			init();
		}
	}
	
	public void edit(){
		questaoBaseList = InitUtil.initQuestaoBaseList();
		palavraChaveList = InitUtil.initPalavraChaveList();
		alternativaBaseInstance = new AlternativaBase();
		palavraChaveInstance = new PalavraChave();
		questaoBaseTemp = new QuestaoBase();
		questaoEmEdicao = true;
		alternativaBaseTemp = new AlternativaBase();
		alternativaCorretaTemp = new AlternativaBase();
		palavraChaveTemp = new PalavraChave();
	}
	
	public void desistirEdit(){
		try {
			questaoBaseInstance = questaoRN.getQuestao(questaoBaseInstance.getId());
		} catch (DAOException e) {
			e.printStackTrace();
			questaoBaseInstance = new QuestaoBase();
		}
		alternativaBaseList = questaoBaseInstance.getAlternativas();
		alternativaCorretaInstance = questaoBaseInstance.getAlternativaCorreta();
		palavraChaveInstance = questaoBaseInstance.getPalavraChave();
	}
	
	public void delete(){
		if(questaoBaseInstanceNaoEhNula()){
			try {
				questaoRN.delete(questaoBaseInstance);
				MsgUtil.msgInfo("Questão removida com sucesso");
				init();
			} catch (DAOException e) {
				MsgUtil.msgError("Erro ao remover questão");
				e.printStackTrace();
			}
		}else{
			MsgUtil.msgError("Selecione uma questão para remover");
		}
	}
	
	public void salvar(){
		questaoBaseInstance.setAlternativas(alternativaBaseList);
		questaoBaseInstance.setAlternativaCorreta(alternativaCorretaInstance);
		questaoBaseInstance.setProfessor(questaoRN.getProfessor(Util.getUsuarioLogado()));
		questaoBaseInstance.setPalavraChave(questaoRN.getPalavraChave(questaoBaseInstance.getPalavraChave().getNome()));
		if(camposObrigatoriosPreenchidos()){
			if(!questaoBaseInstanceNaoEhNula()){
				questaoRN.save(questaoBaseInstance);
				MsgUtil.msgInfo("Questão salva com sucesso");
				questaoEmEdicao = false;
				alternativaBaseInstance = new AlternativaBase();
			}else{
				questaoRN.update(questaoBaseInstance, alternativaRemoverList);
				questaoEmEdicao = false;
				alternativaBaseInstance = new AlternativaBase();
				alternativaRemoverList = new ArrayList<AlternativaBase>();
				MsgUtil.msgInfo("Questão atualizada com sucesso");
			}
		}
	}
	
	private boolean camposObrigatoriosPreenchidos() {
		Boolean temErro = true;
		if(!temAlternativaPreenchida(questaoBaseInstance.getAlternativas())){
			temErro = false;
		}
		if(!questaoBasePreenchida(questaoBaseInstance.getAlternativaCorreta())){
			temErro = false;
		}
		if(!professorPreenchido(questaoBaseInstance.getProfessor())){
			temErro = false;
		}
		if(!palavraChavePreenchida(questaoBaseInstance.getPalavraChave())){
			temErro = false;
		}
		if(questaoBaseInstance.getCodigo() == null || questaoBaseInstance.getCodigo().isEmpty()){
			MsgUtil.msgError("O campo [Código] é obrigatório");
			temErro = false;
		}
		if(questaoBaseInstance.getCabecalho() == null || questaoBaseInstance.getCabecalho().isEmpty()){
			MsgUtil.msgError("O campo [Cabeçalho] é obrigatório");
			temErro = false;
		}
		if(questaoBaseInstance.getGrauDificuldade() == null){
			MsgUtil.msgError("O campo [Grau de Dificuldade] é obrigatório");
			temErro = false;
		}
		return temErro;
	}

	private boolean palavraChavePreenchida(PalavraChave palavraChave) {
		try {
			if(palavraChave.getId() > 0){
				return true;
			}else{
				MsgUtil.msgError("Escolha um assunto para a questão");
				return false;
			}
		} catch (Exception e) {
			MsgUtil.msgError("Escolha um assunto para a questão");
			return false;
		}
	}

	private boolean professorPreenchido(Professor professor) {
		try {
			if(professor.getId() > 0){
				return true;
			}else{
				MsgUtil.msgError("Erro ao encontrar usuário logado");
				return false;
			}
		} catch (Exception e) {
			MsgUtil.msgError("Erro ao encontrar usuário logado");
			return false;
		}
	}

	private boolean questaoBasePreenchida(AlternativaBase alternativaCorreta) {
		try {
			if(alternativaCorreta != null){
				if(alternativaCorreta.getId() != null && alternativaCorreta.getId() > 0){
					return true;
				}else{
					if(alternativaCorreta.getTexto().isEmpty()){
						MsgUtil.msgError("Selecione uma alternativa correta");
						return false;
					}else{
						return true;
					}
				}
			}else{
				return false;
			}
		} catch (Exception e) {
			MsgUtil.msgError("Selecione uma alternativa correta");
			return false;
		}
	}

	private boolean temAlternativaPreenchida(List<AlternativaBase> alternativas) {
		try {
			if(alternativas.size() >= 2){
				if(alternativas.size() > 20){
					MsgUtil.msgError("Só é permitido inserir até vinte alternativas");
					return false;
				}else{
					return true;
				}
			}else{
				MsgUtil.msgError("É necessário inserir no mínimo duas alternativas");
				return false;
			}
		} catch (Exception e) {
			MsgUtil.msgError("É necessário inserir no mínimo duas alternativas");
			return false;
		}
	}

	private boolean questaoBaseInstanceNaoEhNula() {
		try {
			if(questaoBaseInstance.getId() > 0){
				return true;
			}else{
				return false;
			}
		} catch (Exception e) {
			return false;
		}
	}
	
	public void prepararIncluirAlternativa(){
		alternativaBaseInstance = new AlternativaBase();
	}
	
	public void incluirAlternativa(){
		alternativaBaseInstance.setQuestaoBase(questaoBaseInstance);
		if(!alternativaBaseList.contains(alternativaBaseInstance)){
			alternativaBaseList.add(alternativaBaseInstance);
			MsgUtil.msgInfo("Alternativa incluida com sucesso");
		}else{
			MsgUtil.msgError("Esta alternativa já está inserida na lista");
		}
	}
	
	public void prepararEditarAlternativa(){
		alternativaBaseTemp = alternativaBaseInstance;
	}
	
	public void editarAlternativa(){
		int indice = alternativaBaseList.indexOf(alternativaBaseInstance);
		alternativaBaseList.remove(alternativaBaseTemp);
		alternativaBaseList.add(indice, alternativaBaseInstance);
		MsgUtil.msgInfo("Alternativa alterada com sucesso");
	}
	
	public void removerAlternativa(){
		if(alternativaCorretaInstance != null && alternativaCorretaInstance.equals(alternativaBaseInstance)){
			alternativaCorretaInstance = new AlternativaBase();
		}
		if(alternativaBaseInstance != null && alternativaBaseInstance.getId() != null && alternativaBaseInstance.getId() > 0){
			alternativaRemoverList.add(alternativaBaseInstance);
		}
		alternativaBaseList.remove(alternativaBaseInstance);
		alternativaBaseInstance = new AlternativaBase();
		MsgUtil.msgInfo("Alternativa removida com sucesso");
	}
	
	public void marcarAlternativaCorreta(){
		alternativaCorretaInstance = alternativaBaseInstance;
	}
	
	public void prepararAdicionarAssunto(){
		palavraChaveTemp = new PalavraChave();
		palavraChaveList = InitUtil.initPalavraChaveList();
	}
	
	public void adicionarAssunto(){
		palavraChaveInstance = palavraChaveTemp;
		MsgUtil.msgInfo("Assunto incluido com sucesso");
	}
	
	public void selecionarAssunto(){
		if(palavraChaveTempNaoEhNula()){
			palavraChaveInstance = palavraChaveTemp;
			palavraChaveTemp = new PalavraChave();
			palavraChaveList = InitUtil.initPalavraChaveList();
		}else{
			MsgUtil.msgError("Selecione um assunto");
		}
	}
	
	private boolean palavraChaveTempNaoEhNula() {
		try {
			if(palavraChaveTemp.getId() > 0){
				return true;
			}else{
				return false;
			}
		} catch (Exception e) {
			return false;
		}
	}
	
	public void prepararBuscaQuestao(){
		questaoBaseList = InitUtil.inicializaQuestaoBaseList();
		variavelBusca = "";
		varBuscaAssunto = "";
		varBuscaCabecalho = "";
		varBuscaDificuldade = null;
		questaoBaseTemp = new QuestaoBase();
	}

	public void buscarQuestao(){
		questaoBaseList = new LazyDataModel<QuestaoBase>() {
			
			@Override
			public List<QuestaoBase> load(int first, int pageSize, String sortField,
					boolean sortOrder, Map<String, String> arg4) {
				try {
					return questaoRN.listarQuestoes(variavelBusca, varBuscaAssunto, varBuscaCabecalho, varBuscaDificuldade, first, pageSize, sortField, sortOrder);
				} catch (DAOException e) {
					e.printStackTrace();
					return new ArrayList<QuestaoBase>();
				}
			}
		};
		try {
			questaoBaseList.setRowCount(questaoRN.listarQuestoesCount(variavelBusca, varBuscaAssunto, varBuscaCabecalho, varBuscaDificuldade));
		} catch (DAOException e) {
			e.printStackTrace();
			questaoBaseList.setRowCount(0);
		}
		questaoBaseList.setPageSize(5);
	}
	
	public void selecionarQuestao(){
		if(questaoBaseTempNaoEhNula()){
			try {
				questaoBaseInstance = questaoRN.getQuestao(questaoBaseTemp.getId());
				alternativaBaseList = questaoBaseInstance.getAlternativas();
				alternativaCorretaInstance = questaoBaseInstance.getAlternativaCorreta();
				palavraChaveInstance = questaoBaseInstance.getPalavraChave();
			} catch (DAOException e) {
				e.printStackTrace();
				questaoBaseInstance = new QuestaoBase();
			}
			questaoBaseTemp = new QuestaoBase();
			questaoBaseList = InitUtil.initQuestaoBaseList();
		}else{
			MsgUtil.msgError("Selecione uma questão");
		}
	}
	
	private boolean questaoBaseTempNaoEhNula() {
		try {
			if(questaoBaseTemp.getId() > 0){
				return true;
			}else{
				return false;
			}
		} catch (Exception e) {
			return false;
		}
	}
	
	public void alternativaUnSelect(UnselectEvent event){
		alternativaBaseInstance = new AlternativaBase();
	}

	/*
	 * Inicialização de Variáveis
	 */
	
	public void init(){
		questaoRN = new QuestaoRN();
		initLista();
		initInstancia();
		initTemp();
	}
	
	private void initLista(){
		questaoBaseList = InitUtil.initQuestaoBaseList();
		questaoBaseList.setPageSize(5);
		
		alternativaBaseList = new ArrayList<AlternativaBase>();
		palavraChaveList = InitUtil.initPalavraChaveList();
		alternativaRemoverList = new ArrayList<AlternativaBase>();
	}
	
	private void initInstancia(){
		questaoBaseInstance = new QuestaoBase();
		questaoBaseInstance.setPalavraChave(new PalavraChave());
		alternativaBaseInstance = new AlternativaBase();
		alternativaCorretaInstance = new AlternativaBase();
		palavraChaveInstance = new PalavraChave();
		Usuario usuario = Util.getUsuarioLogado();
		if(usuario instanceof Professor){
			professorInstance = questaoRN.getProfessor(usuario);
		}else{
			professorInstance = new Professor();
		}
	}
	
	private void initTemp(){
		questaoBaseTemp = new QuestaoBase();
		alternativaBaseTemp = new AlternativaBase();
		alternativaCorretaTemp = new AlternativaBase();
		palavraChaveTemp = new PalavraChave();
		variavelBusca = "";
		variavelBuscaAssunto = "";
		varBuscaAssunto = "";
		varBuscaCabecalho = "";
		varBuscaCabecalho = null;
		questaoEmEdicao = false;
	}
	
	/*
	 * GETTERS AND SETTERS
	 */

	public LazyDataModel<QuestaoBase> getQuestaoBaseList() {
		return questaoBaseList;
	}

	public void setQuestaoBaseList(LazyDataModel<QuestaoBase> questaoBaseList) {
		this.questaoBaseList = questaoBaseList;
	}

	public List<AlternativaBase> getAlternativaBaseList() {
		return alternativaBaseList;
	}

	public void setAlternativaBaseList(List<AlternativaBase> alternativaBaseList) {
		this.alternativaBaseList = alternativaBaseList;
	}

	public LazyDataModel<PalavraChave> getPalavraChaveList() {
		return palavraChaveList;
	}

	public void setPalavraChaveList(LazyDataModel<PalavraChave> palavraChaveList) {
		this.palavraChaveList = palavraChaveList;
	}

	public QuestaoBase getQuestaoBaseInstance() {
		return questaoBaseInstance;
	}

	public void setQuestaoBaseInstance(QuestaoBase questaoBaseInstance) {
		this.questaoBaseInstance = questaoBaseInstance;
	}

	public AlternativaBase getAlternativaBaseInstance() {
		return alternativaBaseInstance;
	}

	public void setAlternativaBaseInstance(AlternativaBase alternativaBaseInstance) {
		this.alternativaBaseInstance = alternativaBaseInstance;
	}

	public AlternativaBase getAlternativaCorretaInstance() {
		return alternativaCorretaInstance;
	}

	public void setAlternativaCorretaInstance(
			AlternativaBase alternativaCorretaInstance) {
		this.alternativaCorretaInstance = alternativaCorretaInstance;
	}

	public PalavraChave getPalavraChaveInstance() {
		return palavraChaveInstance;
	}

	public void setPalavraChaveInstance(PalavraChave palavraChaveInstance) {
		this.palavraChaveInstance = palavraChaveInstance;
	}

	public QuestaoBase getQuestaoBaseTemp() {
		return questaoBaseTemp;
	}

	public void setQuestaoBaseTemp(QuestaoBase questaoBaseTemp) {
		this.questaoBaseTemp = questaoBaseTemp;
	}

	public AlternativaBase getAlternativaBaseTemp() {
		return alternativaBaseTemp;
	}

	public void setAlternativaBaseTemp(AlternativaBase alternativaBaseTemp) {
		this.alternativaBaseTemp = alternativaBaseTemp;
	}

	public AlternativaBase getAlternativaCorretaTemp() {
		return alternativaCorretaTemp;
	}

	public void setAlternativaCorretaTemp(AlternativaBase alternativaCorretaTemp) {
		this.alternativaCorretaTemp = alternativaCorretaTemp;
	}

	public PalavraChave getPalavraChaveTemp() {
		return palavraChaveTemp;
	}

	public void setPalavraChaveTemp(PalavraChave palavraChaveTemp) {
		this.palavraChaveTemp = palavraChaveTemp;
	}

	public String getVariavelBusca() {
		return variavelBusca;
	}

	public void setVariavelBusca(String variavelBusca) {
		this.variavelBusca = variavelBusca;
	}

	public String getVariavelBuscaAssunto() {
		return variavelBuscaAssunto;
	}

	public void setVariavelBuscaAssunto(String variavelBuscaAssunto) {
		this.variavelBuscaAssunto = variavelBuscaAssunto;
	}

	public Boolean getQuestaoEmEdicao() {
		return questaoEmEdicao;
	}

	public void setQuestaoEmEdicao(Boolean questaoEmEdicao) {
		this.questaoEmEdicao = questaoEmEdicao;
	}

	public Professor getProfessorInstance() {
		return professorInstance;
	}

	public void setProfessorInstance(Professor professorInstance) {
		this.professorInstance = professorInstance;
	}

	public String getVarBuscaAssunto() {
		return varBuscaAssunto;
	}

	public void setVarBuscaAssunto(String varBuscaAssunto) {
		this.varBuscaAssunto = varBuscaAssunto;
	}

	public TipoGrauDificuldade getVarBuscaDificuldade() {
		return varBuscaDificuldade;
	}

	public void setVarBuscaDificuldade(TipoGrauDificuldade varBuscaDificuldade) {
		this.varBuscaDificuldade = varBuscaDificuldade;
	}

	public String getVarBuscaCabecalho() {
		return varBuscaCabecalho;
	}

	public void setVarBuscaCabecalho(String varBuscaCabecalho) {
		this.varBuscaCabecalho = varBuscaCabecalho;
	}

	public List<AlternativaBase> getAlternativaRemoverList() {
		return alternativaRemoverList;
	}

	public void setAlternativaRemoverList(
			List<AlternativaBase> alternativaRemoverList) {
		this.alternativaRemoverList = alternativaRemoverList;
	}
	
}
